package com.wjd.wshow.service.impl;

import com.wjd.wshow.common.resource.Resource;
import com.wjd.wshow.common.resource.ResourceType;
import com.wjd.wshow.entity.Catalog;
import com.wjd.wshow.repository.CatalogRepository;
import com.wjd.wshow.service.CatalogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.file.Path;
import java.util.List;

@Service("CatalogService")
public class CatalogServiceImpl extends BaseServiceImpl<Catalog, String> implements CatalogService {

    private static Logger logger = LoggerFactory.getLogger(CatalogServiceImpl.class);

    private final CatalogRepository catalogRepository;

    public CatalogServiceImpl(CatalogRepository catalogRepository) {
        this.catalogRepository = catalogRepository;
    }

    @Transactional
    @Override
    public synchronized String createCatalog(Resource resource) {
        if (resource == null) {
            return null;
        }
        Catalog parent = createCatalogPath(resource.getType(), resource.getPath());
        if (parent == null) {
            throw new IllegalArgumentException("Parent catalog not exist: " + resource.getPath());
        }
        String resourceName = resource.getPath().getFileName().toString();
        Catalog catalog = catalogRepository.getChildByName(parent.getId(), resourceName);
        if (catalog != null) {
            throw new IllegalArgumentException("Resource catalog has exist: " + resource.getPath());
        }

        catalog = new Catalog();
        catalog.setName(resourceName);
        catalog.setPid(parent.getId());
        catalog.setResId(resource.getResId());
        catalog.setResType(resource.getType());
        catalogRepository.saveAndFlush(catalog);
        logger.info("Create resource catalog: " + resource.getResId());
        return catalog.getId();
    }

    /**
     * 创建资源路径（文件夹路径）
     * @param resourcePath 资源路径
     * @return 返回最后一层的资源节点，也就是资源存放的父目录
     */
    private synchronized Catalog createCatalogPath(ResourceType resourceType, Path resourcePath) {
        if (resourcePath == null) {
            throw new IllegalArgumentException("Catalog path is null!");
        }
        // 先创建资源目录
        String resourceTypeName = resourceType.name();
        Catalog parent = catalogRepository.getChildByName("root", resourceTypeName);
        if (parent == null) {
            parent = new Catalog();
            parent.setName(resourceTypeName);
            parent.setPid("root");
            parent.setResType(ResourceType.FOLDER);
            parent.setResId(resourceTypeName);
            parent = catalogRepository.saveAndFlush(parent);
            logger.info("Create resource type catalog: " + parent.getResId());
        }

        // 再创建子目录节点，不包括最后的资源节点
        Path catalogPath = resourcePath.getParent();
        for (Path path : catalogPath) {
            String childName = path.toString();
            Catalog child = catalogRepository.getChildByName(parent.getId(), childName);
            if (child == null) {
                child = new Catalog();
                child.setName(childName);
                child.setPid(parent.getId());
                child.setResType(ResourceType.FOLDER);
                child.setResId(childName);
                child = catalogRepository.saveAndFlush(child);
                logger.info("Create folder catalog: " + child.getResId());
            }
            parent = child;
        }
        return parent;
    }

    /**
     * 需要递归删除所有子节点
     * @param catalog 目录节点
     */
    @Transactional
    @Override
    public void delete(Catalog catalog) {
        if (catalog == null) {
            return;
        }
        List<Catalog> children = catalogRepository.getChildren(catalog.getId());
        for (Catalog c : children) {
            delete(c);
        }
        catalogRepository.delete(catalog);
        logger.info("Delete catalog: " + catalog.getId());
    }

    @Override
    public void deleteById(String id) {
        Catalog catalog = get(id);
        if (catalog == null) {
            logger.info("Delete catalog not exist: " + id);
            return;
        }
        delete(catalog);
    }

    @Override
    public void deleteByResId(String resId) {
        Catalog catalog = getByResId(resId);
        if (catalog == null) {
            logger.info("Delete resource catalog not exist: " + resId);
            return;
        }
        delete(catalog);
    }

    @Override
    public Catalog getByResId(String resId) {
        Catalog catalog;
        if (resId == null) {
            return null;
        }
        catalog = catalogRepository.getByResId(resId);
        return catalog;
    }

    @Override
    public List<Catalog> getChildren(String id) {
        List<Catalog> catalogs;
        if (id == null) {
            id = "root";
        }
        catalogs = catalogRepository.getChildren(id);
        return catalogs;
    }

    @Override
    protected CatalogRepository getRepository() {
        return catalogRepository;
    }
}
